/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bangcommunity.bbframe.common.utils;

import com.bangcommunity.bbframe.common.utils.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 金鑫
 * 
 * @author jinxin
 *
 */
public class DateUtils {
    private static Logger logger = LoggerFactory.getLogger(DateUtils.class);

    private static final GregorianCalendar calendar = (GregorianCalendar) GregorianCalendar.getInstance();

    public static final Date FIRST_DATE = new Date(0);

    /**
     * list all dates between start date and end date, both day included
     *
     * @param start
     * @param end
     * @return
     */
    public static List<Date> listDates(Date start, Date end) {
        List<Date> dates = new ArrayList<>();

        Date date = start;
        calendar.setTime(start);
        while (date.before(end)) {
            dates.add(date);
            calendar.add(Calendar.DAY_OF_WEEK, 1);
            date = calendar.getTime();
        }
        if (date.equals(end)) {
            dates.add(end);
        }

        return dates;
    }

    /**
     * return the 0'clock time for a date, like 2013/8/1 0:0:0
     *
     * @param date
     * @return
     */
    public static Date get0OClock(Date date) {
        if (date == null) {
            return null;
        }

        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.set(year, month, day, 0, 0, 0);
        return calendar.getTime();
    }

    public static Date parse(final String str, final String pattern) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(str);
        } catch (Exception e) {
            return null;
        }
    }

    public static String format(final Date date, final String pattern) {
        if (date == null) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            return sdf.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    public static int daysBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            logger.warn("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
            return 0;
        }
        Calendar fromCalendar = Calendar.getInstance();
        fromCalendar.setTime(startDate);
        fromCalendar.set(Calendar.HOUR_OF_DAY, 0);
        fromCalendar.set(Calendar.MINUTE, 0);
        fromCalendar.set(Calendar.SECOND, 0);
        fromCalendar.set(Calendar.MILLISECOND, 0);

        Calendar toCalendar = Calendar.getInstance();
        toCalendar.setTime(endDate);
        toCalendar.set(Calendar.HOUR_OF_DAY, 0);
        toCalendar.set(Calendar.MINUTE, 0);
        toCalendar.set(Calendar.SECOND, 0);
        toCalendar.set(Calendar.MILLISECOND, 0);

        return (int) ((toCalendar.getTime().getTime() - fromCalendar.getTime().getTime()) / (1000 * 60 * 60 * 24));
    }

    public static int yearsBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            logger.debug("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
            return 0;
        }
        int startYear = getYear(startDate);
        int endYear = getYear(endDate);
        int i = endYear - startYear;
        return Math.max(i, 1);
    }

    /**
     * 获取指定日期的年份
     *
     * @param date
     * @return
     */
    public static int getYear(Date date) {

        if (null == date)
            return -1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取指定日期的年份
     *
     * @return
     */
    public static int getYear(long millis) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);

        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取指定日期的月份
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {

        if (null == date)
            return -1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return (calendar.get(Calendar.MONTH) + 1);
    }

    /**
     * 获取指定日期的月份
     *
     * @return
     */
    public static int getMonth(long millis) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);

        return (calendar.get(Calendar.MONTH) + 1);
    }

    /**
     * 获取指定的日期的日(月份中的天数)
     *
     * @param date
     * @return
     */
    public static int getDay(Date date) {

        if (null == date)
            return -1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取指定的日期的日(月份中的天数)
     *
     * @return
     */
    public static int getDay(long millis) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);

        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取指定的日期的日(年份中的天数)
     *
     * @param date
     * @return
     */
    public static int getDayOfYear(Date date) {

        if (null == date)
            return -1;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(Calendar.DAY_OF_YEAR);
    }

    /**
     * 获取指定的日期的日(年中的天数)
     *
     * @return
     */
    public static int getDayOfYear(long millis) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);

        return calendar.get(Calendar.DAY_OF_YEAR);
    }
    public static int getMinutes(long timeMs ) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timeMs);

        return calendar.get(Calendar.MINUTE);
    }
    public static int getMinutes(Date date) {
        if (null == date)
            return -1;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(Calendar.MINUTE);
    }
    public static int getHour(long timeMs ) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timeMs);

        return calendar.get(Calendar.HOUR_OF_DAY);
    }
    public static int getHour(Date date) {
        if (null == date)
            return -1;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 某日期前几天
     * 
     * @param date
     * @param day
     *            负数
     * @return
     */
    public static Date before(Date date, Integer day) {
        Calendar beforeNow = Calendar.getInstance();
        beforeNow.setTime(date);
        beforeNow.add(Calendar.DATE, day);// 你要加减的日期
        return beforeNow.getTime();

    }

    /**
     * 返回某天的开始时间
     * 
     * @param date
     * @return
     */
    public static Date begin(Date date) {
        if (null == date) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MINUTE, 0);
        return c.getTime();
    }

    /**
     * 返回某天的结束时间
     * 
     * @param date
     * @return
     */
    public static Date end(Date date) {
        if (null == date) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MINUTE, 59);
        return c.getTime();
    }

    /**
     * 返回某天的开始时间
     * 
     * @param date
     * @return
     */
    public static String begin(String date) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        try {
            return format(begin(parse(date, "yyyy-MM-dd")), "yyyy-MM-dd HH:mm:ss");
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 返回某天的结束时间
     * 
     * @param date
     * @return
     */
    public static String end(String date) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        try {
            return format(end(parse(date, "yyyy-MM-dd")), "yyyy-MM-dd HH:mm:ss");
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 两个时间中相差多少秒
     * 
     * @param startDate
     * @param endDate
     * @return
     */
    public static int secondsBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            logger.warn("空日期无法计算间隔日期,start:{} , endDate:{}", startDate, endDate);
            return 0;
        }
        Calendar fromCalendar = Calendar.getInstance();
        fromCalendar.setTime(startDate);
        Calendar toCalendar = Calendar.getInstance();
        toCalendar.setTime(endDate);
        return (int) ((toCalendar.getTime().getTime() - fromCalendar.getTime().getTime()) / (1000));
    }

    /**
     * 返回某月的开始时间
     * 
     * @param date
     * @return
     */
    public static Date getFirstDateOfMonth(Date date) {
        if (null == date) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
        return c.getTime();
    }

    /**
     * 返回某月的结束时间
     * 
     * @param date
     * @return
     */
    public static Date getLastDateOfMonth(Date date) {
        if (null == date) {
            return null;
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MINUTE, 59);
        return c.getTime();
    }

    /**
     * 返回某年的开始时间
     * 
     * @param date
     * @return
     */
    public static Date getFirstDateOfYear(Date date) {
        if (null == date) {
            return null;
        }
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        calendar.set(year, 0, 1, 0, 0, 0);
        return calendar.getTime();
    }

    /**
     * 返回某月的结束时间
     * 
     * @param date
     * @return
     */
    public static Date getLastDateOfYear(Date date) {
        if (null == date) {
            return null;
        }
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        calendar.set(year, 12, 31, 23, 59, 59);
        return calendar.getTime();
    }

    /**
     * 日期只保留年月日，清除时分秒
     */
    public static String clearTimeOfDate(String date) {
        int dateLength = 10;
        if (null == date) {
            return null;
        }
        date = date.trim();
        if (StringUtils.isNotBlank(date) && date.length() > dateLength) {
            return date.substring(0, dateLength);
        }
        return date;
    }

    /**
     * 日期格式字符串转换成时间戳
     *
     * @param dateStr
     *            字符串日期
     * @param format
     *            如：yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    public static Long date2TimeStamp(String dateStr, String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.parse(dateStr).getTime() / 1000;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0l;
    }

    /**
     * Java将Unix时间戳转换成指定格式日期字符串
     * 
     * @param timestampString
     *            时间戳 如："1473048265";
     * @param formats
     *            要格式化的格式 默认："yyyy-MM-dd HH:mm:ss";
     *
     * @return 返回结果 如："2016-09-05 16:06:42";
     */
    public static String timeStamp2Date(String timestampString, String formats) {
        if (formats == "") {
            formats = "yyyy-MM-dd HH:mm:ss";
        }
        Long timestamp = Long.parseLong(timestampString) * 1000;
        String date = new SimpleDateFormat(formats, Locale.CHINA).format(new Date(timestamp));
        return date;
    }

    /**
     * 增加年
     * 
     * @param date
     * @param nYear
     * @return
     */
    public static Date addYear(Date date, int nYear) {
        return add(date, nYear, Calendar.YEAR);
    }

    /**
     * 增加月份
     * 
     * @param date
     * @param nMonth
     * @return
     */
    public static Date addMonth(Date date, int nMonth) {
        return add(date, nMonth, Calendar.MONTH);
    }

    /**
     * 增加天数
     * 
     * @param date
     * @param nMonth
     * @return
     */
    public static Date addDay(Date date, int nMonth) {
        return add(date, nMonth, Calendar.DAY_OF_MONTH);
    }

    /**
     * 增加小时
     * 
     * @param date
     * @param hours
     * @return
     */
    public static Date addHour(Date date, int hours) {
        return add(date, hours, Calendar.HOUR_OF_DAY);
    }

    /**
     * 日期增加
     * 
     * @param date
     * @param num
     * @param type
     * @return
     */
    public static Date add(Date date, int num, int type) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(type, num);
        Date result = cal.getTime();
        return result;
    }

    public static void main(String[] args) {
        long start = DateUtils.parse("2017-02-01 10:00:00", "yyyy-MM-dd HH:mm:ss").getTime();
        long end = DateUtils.parse("2017-02-01 10:20:00", "yyyy-MM-dd HH:mm:ss").getTime();
        System.out.println(start);
        System.out.println(end);
        System.out.println(new Date(1487562495823L));
        Date d = new Date();
        System.out.println(addDay(d, 2) + "" + addDay(d, -1));
        System.out.println(
                daysBetween(parse("20160702010101", "yyyyMMddHHmmss"), parse("20160702020101", "yyyyMMddHHmmss")));
        System.out.println(
                daysBetween(parse("20160702010101", "yyyyMMddHHmmss"), parse("20160702020101", "yyyyMMddHHmmss")));
    }
}
